# coding = utf-8
import os
import socket
import time
import threading
import fnmatch
import FaceTrain
import FaceRecognition
from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(max_workers=3)


def unpack(total_data):
    # print(self.total_data[0],self.total_data[-1])
    global name_list
    global name_id
    name = None
    Id = None
    frame = None
    if total_data[0] == ord(b'\xaa') and total_data[-1] == ord(b'\xbb'):
        NameLenIndex = 1
        NameLen = total_data[NameLenIndex]
        IdLenIndex = 3 + NameLen -1
        IdLen = total_data[IdLenIndex]
        FrameLenIndex = 5 + NameLen -1
        FrameLenHigh = total_data[FrameLenIndex]
        FrameLenLow = total_data[FrameLenIndex+1]
        FrameLen = FrameLenHigh<<8 | FrameLenLow
        print("NameLen:{},IdLen:{},FrameLen:{}".format(NameLen,IdLen,FrameLen))
        name = total_data[NameLenIndex+1:NameLenIndex+NameLen+1]
        name = name.decode('utf-8')
        Id = total_data[IdLenIndex+1:IdLenIndex+IdLen+1]
        Id = int.from_bytes(Id, byteorder='big')
        frame = total_data[FrameLenIndex+2:-1]
        
        if name not in name_list.keys():
            name_list[name] = name_id
            name_id += 1
    return name,Id,frame

def AddFace(face):
    global name_list
    global name_id
    for data in face:
        name,Id,frame = unpack(data)
        print(name,Id,name_list)
        file = open('./FaceData/{}.{}.{}.jpg'.format(name,name_list[name],Id), 'wb') 
        file.write(frame)
        file.close()
    
    # result = FaceTrain.trainModel()
    # if result == -1:
    #     return -1
    return 0

def DelFace(name):
    global name_list
    global name_id
    directory = './FaceData/'
    files = os.listdir(directory)
    deleted_files = []
    print("name:{}".format(name))
    for file in files:
        if fnmatch.fnmatch(file, f'*{name}*'):
            file_path = os.path.join(directory, file)  
            try:
                os.remove(file_path) 
                deleted_files.append(file)  
                print(f"del file... :{file}")
            except Exception as e:
                print(f"Error {file} : {e}")
    
    if not deleted_files:
        print("not find file")
        return -1
    else:
        del name_list[name]
        # FaceTrain.trainModel()
        return 0

def RcgeFace(face):
    global name_list
    global name_id
    if face[0] == ord(b'\xaa') and face[-1] == ord(b'\xbb'):
        name_len = face[1]
        name = face[2:2+name_len]
        name = name.decode('utf-8')
        frame_len_highByte = face[1+name_len+1]
        frame_len_lowByte = face[1+name_len+1+1]
        frame_len = (frame_len_highByte << 8) | (frame_len_lowByte)
        frame = face[1+name_len+2+1:-1]

        print(name)
        file = open('./{}.jpg'.format(name), 'wb') 
        file.write(frame)
        file.close()

        if name in name_list.keys():
            return 0
    return -1
def handle_client(client_socket):
    global name_list
    global name_id
    message_len=0

    AddFace_total_data = bytes()
    AddFace_total_len=0
    
    DelFace_total_data = bytes()
    DelFace_total_len=0

    RcgeFace_total_data = bytes()
    RcgeFace_total_len=0

    request_type = 0
    data_list = []
    while True:
        message_head = client_socket.recv(3)
        request_type = message_head[0]
        message_len = message_head[1]<<8 | message_head[2]
        print(message_head,request_type,message_len)
        if not message_head:                #disconnect
            client_socket.close()
            return -1
        elif request_type == 0x01:      #recognize face
            while True:
                data = client_socket.recv(1024)
                if not data:                    #disconnect
                    client_socket.close()
                    return -1
                else:                           #recving...
                    print("rece data len : {}".format(len(data)))
                    RcgeFace_total_data += data
                    RcgeFace_total_len += len(data)
                    if RcgeFace_total_len == message_len:#recv 1 frame over
                        print("Recv rcge face")

                        rcgetask = executor.submit(RcgeFace, RcgeFace_total_data)
                        result = rcgetask.result()
                        if result == 0:
                            client_socket.send(bytes([0xEE,0xEE]))
                        elif result == -1:
                            client_socket.send(bytes([0x1F,0x1F]))

                        RcgeFace_total_len=0
                        message_len=0
                        RcgeFace_total_data = bytes()
                        break
        elif request_type == 0x02:      #delete face
            while True:
                data = client_socket.recv(1024)
                if not data:                    #disconnect
                    client_socket.close()
                    return -1
                else:                           #recving...
                    print("rece data len : {}".format(len(data)))
                    DelFace_total_data += data
                    DelFace_total_len += len(data)
                    if DelFace_total_len == message_len:#recv 1 frame over
                        print("Recv del face")
                        # print(DelFace_total_data.decode('utf-8'))
                        name = DelFace_total_data.decode('utf-8')

                        deltask = executor.submit(DelFace, name)
                        result = deltask.result()
                        if result == 0:
                            client_socket.send(bytes([0xEE,0xEE]))
                        elif result == -1:
                            client_socket.send(bytes([0x1F,0x1F]))

                        DelFace_total_len=0
                        message_len=0
                        DelFace_total_data = bytes()
                        break
        elif request_type == 0x03:      #add face
            if message_len == 0xFFFF:             #recv 30 frame over
                message_len = 0x0000
                print("Recved end flag")

                addtask = executor.submit(AddFace, data_list)
                result = addtask.result()
                if result == 0:
                    client_socket.send(bytes([0xEE,0xEE]))
                elif result == -1:
                    client_socket.send(bytes([0x1F,0x1F]))

                data_list=[]
                # time.sleep(1)
                # client_socket.close() 
                continue
            elif message_len == 0x0000:             #client close
                print("Client close")
                time.sleep(1)
                client_socket.close() 
                break
            while True:
                data = client_socket.recv(1024)
                if not data:                    #disconnect
                    client_socket.close()
                    return -1
                else:                           #recving...
                    print("rece data len : {}".format(len(data)))
                    AddFace_total_data += data
                    AddFace_total_len += len(data)
                    if AddFace_total_len == message_len:#recv 1 frame over
                        print("Recv 1 frame")
                        AddFace_total_len=0
                        message_len=0
                        data_list.append(AddFace_total_data)
                        AddFace_total_data = bytes()
                        break
                
    return 0

if __name__ == "__main__":
    name_list = {}
    name_id = 0

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(("0.0.0.0",5000))
    server_socket.listen(1)
    while True:
        print("Waitting connect...")
        client_socket, client_address = server_socket.accept()
        print(f'Accepted connection from {client_address}')
        client_thread = threading.Thread(target=handle_client, args=(client_socket,))
        client_thread.start()
        client_thread.join()

